/*
 * Copyright (c) Eldanichu  dateRange.js (2024-9-29).
 */




import {StringUtils} from "./StringUtils";
import moment from "dayjs";

export class Calender {
  constructor() {
    this.start = ""
    this.end = ""
    this.format = "YYYY/MM/DD"
    this.dayS = " 00:00"
    this.dayE = " 23:59"
  }
  /**
   * 计算两个日期时间相差的年数、月数、天数、小时数、分钟数、秒数
   * DIFFTIME(开始时间,结束时间,[单位])，单位可以是 "y" 、"M"、"d"、"h"、"m"、"s"'
   * console.log(DIFFTIME('2019-6-30 13:20:00', '2020-10-01 11:20:32', 's'))
   */
  static DIFFTIME(startTime, endTime, unit) {
    // 判断当前月天数
    function getDays(mouth, year) {
      let days = 30
      if (mouth === 2) {
        days = year % 4 === 0 ? 29 : 28
      } else if (mouth === 1 || mouth === 3 || mouth === 5 || mouth === 7 || mouth === 8 || mouth === 10 || mouth === 12) {
        // 月份为：1,3,5,7,8,10,12 时，为大月.则天数为31；
        days = 31
      }
      return days
    }

    const start = new Date(startTime)
    const end = new Date(endTime)
    // 计算时间戳的差
    const diffValue = end - start
    // 获取年
    const startYear = start.getFullYear()
    const endYear = end.getFullYear()
    // 获取月
    const startMouth = start.getMonth() + 1
    const endMouth = end.getMonth() + 1
    // 获取日
    const startDay = start.getDate()
    const endDay = end.getDate()
    // 获取小时
    const startHours = start.getHours()
    const endHours = end.getHours()
    // 获取分
    const startMinutes = start.getMinutes()
    const endMinutes = end.getMinutes()
    // 获取秒
    const startSeconds = start.getSeconds()
    const endSeconds = end.getSeconds()
    // 下方注释两行为调试用
    // console.log('start:', startYear, startMouth, startDay, startHours, startMinutes, startSeconds)
    // console.log('end:', endYear, endMouth, endDay, endHours, endMinutes, endSeconds)
    if (unit === "y" || unit === "M") {
      // 相差年份月份
      const diffYear = endYear - startYear
      // 获取当前月天数
      const startDays = getDays(startMouth, startYear)
      const endDays = getDays(endMouth, endYear)
      const diffStartMouth = (startDays - (startDay + ((startHours * 60 + startMinutes + startSeconds / 60) / 60 / 24) - 1)) / startDays
      const diffEndMouth = (endDay + ((endHours * 60 + endMinutes + endSeconds / 60) / 60 / 24) - 1) / endDays
      const diffMouth = diffStartMouth + diffEndMouth + (12 - startMouth - 1) + endMouth + (diffYear - 1) * 12
      if (unit === "y") {
        return Math.floor(diffMouth / 12 * 100) / 100
      } else {
        return diffMouth
      }
    } else if (unit === "d") {
      return parseInt(diffValue / 1000 / 60 / 60 / 24)
    } else if (unit === "h" || unit === "hour" || unit === "hours") {
      return parseInt(diffValue / 1000 / 60 / 60)
    } else if (unit === "m" || unit === "minutes" || unit === "minute") {
      return parseInt(diffValue / 1000 / 60)
    } else if (unit === "s") {
      return parseInt(diffValue / 1000)
    } else {
      // console.log('请输入正确的单位')
    }
  }

  static formatDate(date, format = "YYYY-MM-DD") {
    if (StringUtils.isEmptyOrNull(date) || !moment(date).isValid()) {
      return ""
    }
    const res = moment(date).format(format)
    return res
  }

  today() {
    const d = moment()

    return [d.format(this.format + this.dayS), d.format(this.format + this.dayE)]
  }

  yesterday() {
    const d = moment().add(-1, "day")

    return [d.format(this.format + this.dayS), d.format(this.format + this.dayE)]
  }

  currentWeek(date) {
    const d = date || new Date()
    const now = d.getTime()
    const day = d.getDay()
    const lt = 24 * 3600 * 1000
    const dd = now - (day - 1) * lt
    const de = now + (7 - day) * lt
    const dst = new Date(dd)
    const det = new Date(de)

    const st = [
      dst.getFullYear(),
      this.padZero(dst.getMonth() + 1),
      this.padZero(dst.getDate())
    ].join("/")

    const et = [
      det.getFullYear(),
      this.padZero(det.getMonth() + 1),
      this.padZero(det.getDate())
    ].join("/")
    return [st, et]
  }

  lastWeek() {
    const d = new Date()
    const now = d.getTime()
    const day = d.getDay()
    const lt = 24 * 3600 * 1000
    const n = lt * 7 * -1
    const dd = now - (day - 1) * lt + n
    const de = now + (7 - day) * lt + n
    const dst = new Date(dd)
    const det = new Date(de)

    const st = [
      dst.getFullYear(),
      this.padZero(dst.getMonth() + 1),
      this.padZero(dst.getDate())
    ].join("/")

    const et = [
      det.getFullYear(),
      this.padZero(det.getMonth() + 1),
      this.padZero(det.getDate())
    ].join("/")
    return [st, et]
  }

  currentMonth(month) {
    const now = new Date()
    const _month = month || (now.getMonth() + 1)

    const st = new Date(now.getFullYear(), (_month - 1), 1)
    const et = new Date(now.getFullYear(), (_month), 0)

    return [moment(st).format(this.format), moment(et).format(this.format)]
  }

  getWeekRangeAsString(year, weekNumber, month = 0) {
    const firstDayOfYear = new Date(year, month, 1)
    const daysToFirstSunday = firstDayOfYear.getDay() // Days until the first Sunday of the year
    const firstSunday = new Date(year, month, 1 + (7 - daysToFirstSunday)) // First Sunday of the year
    const startOfRequestedWeek = new Date(firstSunday)
    startOfRequestedWeek.setDate(startOfRequestedWeek.getDate() + 7 * (weekNumber - 1)) // Start of requested week
    const endOfRequestedWeek = new Date(startOfRequestedWeek)
    endOfRequestedWeek.setDate(endOfRequestedWeek.getDate() + 6) // End of the week
    const startDateString = startOfRequestedWeek.toISOString().split("T")[0] // Convert to string
    const endDateString = endOfRequestedWeek.toISOString().split("T")[0] // Convert to string
    return { st: startDateString, et: endDateString }
  }

  currentMonthValue() {
    const now = new Date()
    return (now.getMonth() + 1)
  }

  getDaysInCurrentMonth(mon) {
    const now = new Date()
    // 设置当前月份和任意日期（这里设置为下个月的第0天）
    now.setMonth(mon || (now.getMonth() + 1), 0)
    // 获取上个月的最后一天，即当前月的天数
    return now.getDate()
  }

  getCurrentSeason(mon) {
    const now = new Date()
    const m = mon || (now.getMonth() + 1)
    let s = 1
    if (m >= 1 && m <= 3) {
      s = 1
    } else if (m >= 4 && m <= 6) {
      s = 2
    } else if (m >= 7 && m <= 9) {
      s = 3
    } else if (m >= 10 && m <= 12) {
      s = 4
    }
    return s
  }

  /**
   * 取日期的第[x]周
   * @param date
   * @returns {number}
   */
  getWeekNumber(date) {
    // 将日期设置为年份的第一天（1月1日）
    date.setMonth(0)
    date.setDate(1)
    date.setHours(0, 0, 0, 0)

    // 获取第一天的星期
    const firstDayOfYear = date.getDay()

    // 使用Date.UTC获取一年的第一天与当前日期的毫秒数之间的差值
    const dayOfYear = (Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) - Date.UTC(date.getFullYear(), 0, 0)) / (24 * 60 * 60 * 1000)

    // 如果第一天是星期四（4），则第一周的开始日期是1月4日，否则从1月1日开始
    const weekNum = Math.ceil((dayOfYear + firstDayOfYear - 1) / 7)

    return weekNum
  }

  lastMonth() {
    const now = new Date()
    const st = new Date(now.getFullYear(), now.getMonth() - 1, 1)
    const et = new Date(now.getFullYear(), now.getMonth(), 0)

    return [moment(st).format(this.format), moment(et).format(this.format)]
  }

  currentYear() {
    const now = new Date()
    const st = new Date(now.getFullYear(), 0, 1)
    const et = new Date(now.getFullYear(), 12, 0)

    return [moment(st).format(this.format), moment(et).format(this.format)]
  }

  lastYear() {
    const now = new Date()
    const st = new Date(now.getFullYear() - 1, 0, 1)
    const et = new Date(now.getFullYear() - 1, 12, 0)

    return [moment(st).format(this.format), moment(et).format(this.format)]
  }

  padZero(number) {
    if (isNaN(number)) {
      throw new Error("number is NaN.")
    }
    return parseInt(number) > 9 ? number : ["0", number].join("")
  }
}
